package edu.mbb.cloud.nacos.listen;

import edu.mbb.cloud.nacos.MbbPropertySourceLocator;
import edu.mbb.cloud.nacos.NacosProperSource;
import org.springframework.beans.BeansException;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.cloud.endpoint.event.RefreshEvent;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationListener;
import org.springframework.util.StringUtils;

import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * 添加监听只会启动一次
 */
public class MyContextRefresher implements ApplicationListener<ApplicationReadyEvent>, ApplicationContextAware {
    private ApplicationContext applicationContext;

    private ConfigService configService;
    private Map<String, Listener> listenerMap = new ConcurrentHashMap<>(16);
    private AtomicBoolean ready = new AtomicBoolean(false);

    public MyContextRefresher(ConfigService nacosConfigProperties){
        this.configService=nacosConfigProperties;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext=applicationContext;
    }

    @Override
    public void onApplicationEvent(ApplicationReadyEvent event) {
        if (this.ready.compareAndSet(false, true)) {
            this.registerNacosListenersForApplications();
        }
    }

    private void registerNacosListenersForApplications() {
            for (String key : MbbPropertySourceLocator.properSourceMap.keySet()) {
                NacosProperSource nacosProperSource = MbbPropertySourceLocator.properSourceMap.get(key);
                String dataId = nacosProperSource.getName();
                registerNacosListener(nacosProperSource.getGroupId(), dataId);
            }
    }

    private void registerNacosListener(final String group, final String dataId) {

        Listener listener = listenerMap.computeIfAbsent(dataId, i -> new Listener() {
            @Override
            public void receiveConfigInfo(String configInfo) {
                String md5 = "";
                if (!StringUtils.isEmpty(configInfo)) {
                    try {
                        MessageDigest md = MessageDigest.getInstance("MD5");
                        md5 = new BigInteger(1, md.digest(configInfo.getBytes("UTF-8")))
                                .toString(16);
                    }
                    catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
                        e.printStackTrace();
                        System.out.println("[Nacos] unable to get md5 for dataId: " + dataId);
                    }
                }
                applicationContext.publishEvent(
                        new RefreshEvent(this, null, "Refresh Nacos config"));
            }

            @Override
            public Executor getExecutor() {
                return null;
            }
        });

        try {
            configService.addListener(dataId, group, listener);
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }
}
